import { defaultEquals, Node, LinkedList } from './LinkedList.js'

/**
 * @class DoublyNode
 * @extends {Node}
 * 
 * prev 指针指向上一个项
 */
class DoublyNode extends Node {
  constructor(element, next, prev){
    super(element, next);
    this._prev = prev;
  }
}

/**
 * @class DoublyLinkedList 双向链表
 * @extends {LinkedList}
 * 
 * insert(element, position)：向链表的特定位置插入一个新元素。
 * removeAt(position)：从链表的特定位置移除一个元素。
 * 
 */
class DoublyLinkedList extends LinkedList {
  constructor(equalsFn = defaultEquals) { 
    super(equalsFn);
    this._tail = undefined; // 记录尾部元素
  }

  insert(element, index){
    if (index >= 0 && index <= this._count) {
      const node = new DoublyNode(element);
      let current = this._head;
      if(index === 0){
        if (this._head == null) {
          this._head = node; 
          this._tail = node; 
        } else { 
          node.next = this._head;
          current._prev = node;
          this._head = node;
        }
      }else if(index === this._count){
        current = this._tail;
        current._next = node;
        node._prev = current;
        node._next = node;
      }else {
        const previous = this.getElementAt(index - 1);
        current = previous._next;
        node._next = current;
        previous._next = node;
        current._prev = node;
        node._prev = previous;
      }

      this._count++;
      return true;
    }

    return false;
  }

  removeAt(index){
    if (index >= 0 && index < this._count) {
      let current = this._head;
      if(index === 0){
        this._head = current._next;
        if (this.count === 1) {
          this._tail = undefined; 
        } else { 
          this._head._prev = undefined;
        }
      }else if(index === this._count - 1){
        current = this._tail;
        this._tail = current._prev;
        this._tail._next = undefined;
      }else {
        current = this.getElementAt(index);
        const previous = current._prev;
        previous._next = current._next;
        current._next._prev = previous;
      }

      this._count--;
      return current._element;
    }

    return undefined;
  }
}